<template>
  <a-form
    :label-col="{ span: 6 }"
    :model="formState"
    :wrapper-col="{ span: 14 }"
    @finish="onFinish"
  >
    <template v-if="isButton()">
      <a-form-item
        :rules="[{ required: true, message: '请输入按钮名称!' }]"
        label="按钮名称"
        name="title"
      >
        <a-input v-model:value="formState['title']" />
      </a-form-item>
      <a-form-item
        label="代码标识"
        name="path"
        required
      >
        <a-input v-model:value="formState['path']" />
      </a-form-item>
    </template>
    <template v-else>
      <a-form-item
        :rules="[{ required: true, message: '请输入菜单名称!' }]"
        label="菜单名称"
        name="title"
      >
        <a-input v-model:value="formState['title']" />
      </a-form-item>
      <a-form-item
        :rules="[{ required: true, message: '请选择一个菜单图标!' }]"
        label="菜单图标"
        name="icon"
      >
        <a-input
          id="iconInput"
          v-model:value="formState['icon']"
          class="icon-input"
          read-only
          @click="selectMenuIcon"
        >
          <template
            v-if="formState['icon'].length"
            #prefix
          >
            <Icon :icon="formState['icon']" />
          </template>
          <template #suffix>
            <a-button
              size="small"
              type="primary"
              @click="onSearch"
            >
              手动输入
            </a-button>
          </template>
        </a-input>
      </a-form-item>
      <a-form-item
        label="是否缓存"
        required
      >
        <a-switch v-model:checked="formState['isCache']" />
      </a-form-item>
      <a-form-item
        label="是否为外链"
        required
      >
        <a-switch v-model:checked="formState['isFrame']" />
      </a-form-item>
      <a-form-item
        label="路由路径"
        name="path"
        required
      >
        <a-input v-model:value="formState['path']" />
      </a-form-item>
      <a-form-item
        label="组件地址"
        name="component"
      >
        <a-input v-model:value="formState['component']" />
      </a-form-item>
      <a-form-item label="路由参数">
        <a-input v-model:value="formState['query']" />
      </a-form-item>
    </template>
    <a-form-item :wrapper-col="{ span: 14, offset: 6 }">
      <div class="form-button-list">
        <a-button @click="resetForm">
          清空
        </a-button>
        <a-button
          html-type="submit"
          type="primary"
        >
          提交
        </a-button>
      </div>
    </a-form-item>
  </a-form>
  <icon-modal
    v-model:icon="formState['icon']"
    v-model:visible="visible"
  />
  <dialog-box
    v-model:visible="inputIconBoxVisible"
    :width="500"
    title="参数修改"
  >
    <a-form
      :model="iconForm"
      label-align="right"
      @finish="inputIconForm"
    >
      <a-form-item
        :rules="[{required: true, message: '请输入图标字符串!'}]"
        label="图标"
        name="icon"
        required
      >
        <a-input
          v-model:value="iconForm['icon']"
          placeholder="请输入图标对应的字符串"
        />
      </a-form-item>
      <a-form-item>
        <a-button
          block
          html-type="submit"
          type="primary"
        >
          确定
        </a-button>
      </a-form-item>
    </a-form>
  </dialog-box>
</template>

<script lang="ts" setup>
import { Ref } from 'vue'

import { addMainMenu, addMenuButton, addSubMenu, updateMainMenu, updateSubMenu } from '@/framework/apis/admin/navEdit'
import DialogBox from '@/framework/components/common/dialogBox/DialogBox.vue'
import { FormState, FormType } from '@/framework/components/common/treeEditForm/type'
import { EDIT } from '@/framework/utils/constant'

let visible: Ref<boolean> = ref(false) //控制图标选择对话框的弹出
let inputIconBoxVisible: Ref<boolean> = ref(false)
let iconForm: Ref<{ icon: string }> = ref({ icon: '' })

// formState：默认表单数据，因为编辑的时候需要展示已有信息， type：用于区别是目前表单应为编辑表单还是新增表单
// menuId: 菜单项Id，用于编辑Sub Menu和Main Menu菜单项和新增Sub Menu菜单项
const props = defineProps<{ formState: FormState, type: FormType, menuId?: number | undefined, grandId?: number | null }>()
let { formState, menuId, type, grandId } = toRefs(props)

// 从父组件中接收两个函数，以更新父组件中相关组件的更新
const updateMainTree = inject('updateMainTree') as () => void
const updateSubTree = inject('updateSubTree') as () => void

// Icon输入框的点击事件，调出IconModal对话框
const selectMenuIcon = () => visible.value = true

// 表单验证成功后的回调函数，整理数据后发送网络请求，并更新父组件中的某些组件
const onFinish = () => {
  if (type.value === EDIT && menuId && typeof menuId.value === 'number') {
    const data = { ...formState.value, menuId: menuId.value }
    data['isCache'] = +data['isCache']
    data['isFrame'] = +data['isFrame']
    // grandId 有值，说明操作的是SubMenu，则需要更新updateSubTree；否则，需要更新updateMainTree
    if (grandId && grandId.value) updateSubMenu(data).then(updateSubTree)
    else updateMainMenu(data).then(updateMainTree)
  } else if (type.value === 'add_menu') {
    const data = toRaw(formState.value)
    // grandId 有值，说明当前需要新增SubMenu菜单，需要在发送请求的时候带上grandId
    if (grandId && typeof grandId.value === 'number') data['grandId'] = grandId.value
    data['isCache'] = +data['isCache']
    data['isFrame'] = +data['isFrame']
    if (grandId && grandId.value) addSubMenu(data).then(updateSubTree).then(resetForm)
    else addMainMenu(data).then(updateMainTree).then(resetForm)
  } else if (type.value === 'add_button') {
    const data = toRaw(formState.value)
    // grandId 有值，说明当前需要新增SubMenu菜单，需要在发送请求的时候带上grandId
    if (grandId && typeof grandId.value === 'number') data['grandId'] = grandId.value
    data['icon'] = 'SelectOutlined'
    if (grandId && grandId.value) addMenuButton(data).then(updateSubTree).then(resetForm)
  }
}

const isButton = () => {
  return type.value === 'add_button' ||
    (type.value === EDIT && formState.value.menuType === 3)
}

const onSearch = () => inputIconBoxVisible.value = true

const inputIconForm = () => {
  formState.value.icon = iconForm.value.icon
  inputIconBoxVisible.value = false
}

// 清空表单内容
const resetForm = () => {
  formState.value.title = ''
  formState.value.icon = 'SettingOutlined'
  formState.value.isCache = false
  formState.value.isFrame = false
  formState.value.path = ''
  formState.value.query = ''
}

// 手动触发表单验证，只用于处理Icon Input中的图标选择后，更新form的更新状态
watch(() => formState.value.icon, () => {
  // 因为js为input赋值的时候，不会触发input的change等方法，所以需要手动定义一个change事件，并在对应的input元素上触发
  // 目的是更新form的验证状态，antd是根据input的change事件，更新的表单验证状态
  const changeEvent = new Event('change')
  const iconInput = document.getElementById('iconInput') as HTMLInputElement
  iconInput?.dispatchEvent(changeEvent)
})

onMounted(() => (type.value === 'add_menu' || type.value === 'add_button') && resetForm())

</script>
<style>
.icon-input, .icon-input input .ant-input {
  cursor: pointer !important;
}
.form-button-list {
  display: flex;
  justify-content: space-between;
}
.form-button-list button {
  width: 45%;
}
</style>
